package com.zenithmind.gateway.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 网关服务全局异常处理器
 * 针对WebFlux架构特别设计，处理网关路由和转发过程中的异常
 */
@Slf4j
@Order(-1)
@Configuration
public class GatewayServiceGlobalExceptionHandler implements ErrorWebExceptionHandler {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        
        if (response.isCommitted()) {
            return Mono.error(ex);
        }

        // 设置响应的Content-Type为JSON
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        
        if (ex instanceof ResponseStatusException) {
            response.setStatusCode(((ResponseStatusException) ex).getStatusCode());
        } else {
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        // 构建错误响应
        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory bufferFactory = response.bufferFactory();
            try {
                Result<Void> errorResult;
                if (ex instanceof ResponseStatusException) {
                    ResponseStatusException responseStatusException = (ResponseStatusException) ex;
                    errorResult = Result.fail(responseStatusException.getStatusCode().value(), 
                            responseStatusException.getReason(), null);
                } else {
                    log.error("网关异常", ex);
                    errorResult = Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), 
                            "网关服务异常: " + ex.getMessage(), null);
                }
                
                byte[] errorBytes = objectMapper.writeValueAsBytes(errorResult);
                return bufferFactory.wrap(errorBytes);
            } catch (JsonProcessingException e) {
                log.error("Error writing response", e);
                return bufferFactory.wrap(new byte[0]);
            }
        }));
    }
} 